package org.jeecg.modules.wmhb.controller;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.wmhb.entity.WmPurchaseOrderDetail;
import org.jeecg.modules.wmhb.service.IWmPurchaseOrderDetailService;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;

import org.jeecg.modules.wmhb.util.WmhbUtil;
import org.jeecg.modules.wmhb.vo.WmPurchaseOrderDetailResult;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.apache.shiro.authz.annotation.RequiresPermissions;

/**
 * @Description: 采购订货
 * @Author: jeecg-boot
 * @Date: 2024-11-01
 * @Version: V1.0
 */
@Api(tags = "采购订货")
@RestController
@RequestMapping("/wmhb/purchaseOrderDetail")
@Slf4j
public class WmPurchaseOrderDetailController extends JeecgController<WmPurchaseOrderDetail, IWmPurchaseOrderDetailService> {
    @Autowired
    private IWmPurchaseOrderDetailService purchaseOrderDetailService;

    /**
     * 分页列表查询
     *
     * @param purchaseOrderDetail
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    //@AutoLog(value = "采购订货-分页列表查询")
    @ApiOperation(value = "采购订货-分页列表查询", notes = "采购订货-分页列表查询")
    @GetMapping(value = "/list")
    public Result<IPage<WmPurchaseOrderDetail>> queryPageList(WmPurchaseOrderDetail purchaseOrderDetail,
                                                              @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                                              @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                                              HttpServletRequest req) {
        QueryWrapper<WmPurchaseOrderDetail> queryWrapper = QueryGenerator.initQueryWrapper(purchaseOrderDetail, req.getParameterMap());
        Page<WmPurchaseOrderDetail> page = new Page<WmPurchaseOrderDetail>(pageNo, pageSize);
        IPage<WmPurchaseOrderDetail> pageList = purchaseOrderDetailService.page(page, queryWrapper);
        return Result.OK(pageList);
    }

    /**
     * 添加
     *
     * @param purchaseOrderDetail
     * @return
     */
    @AutoLog(value = "采购订货-添加")
    @ApiOperation(value = "采购订货-添加", notes = "采购订货-添加")
    @RequiresPermissions("wmhb:purchase_order_detail:add")
    @PostMapping(value = "/add")
    public Result<String> add(@RequestBody WmPurchaseOrderDetail purchaseOrderDetail) {
        purchaseOrderDetailService.save(purchaseOrderDetail);
        return Result.OK("添加成功！");
    }

    /**
     * 编辑
     *
     * @param purchaseOrderDetail
     * @return
     */
    @AutoLog(value = "采购订货-编辑")
    @ApiOperation(value = "采购订货-编辑", notes = "采购订货-编辑")
    @RequiresPermissions("wmhb:purchase_order_detail:edit")
    @RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
    public Result<String> edit(@RequestBody WmPurchaseOrderDetail purchaseOrderDetail) {
        purchaseOrderDetailService.updateById(purchaseOrderDetail);
        return Result.OK("编辑成功!");
    }

    /**
     * 批量到货
     *
     * @param ids
     * @param factArriveTime
     * @return
     */
    @AutoLog(value = "采购订货-批量到货")
    @ApiOperation(value = "采购订货-批量到货", notes = "采购订货-批量到货")
    @RequiresPermissions("wmhb:purchase_order_detail:arriveBatch")
    @RequestMapping(value = "/arriveBatch", method = {RequestMethod.PUT, RequestMethod.POST})
    public Result<String> arriveBatch(@RequestParam(name = "ids", required = true) String ids, @RequestParam(name = "factArriveTime", required = true) String factArriveTime) {
        List<String> idList = Arrays.asList(ids.split(","));
        if(idList.isEmpty()){
            return Result.error("ids参数为空");
        }

        purchaseOrderDetailService.arriveBatch(idList, factArriveTime);
        return Result.OK("操作成功!");
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AutoLog(value = "采购订货-通过id删除")
    @ApiOperation(value = "采购订货-通过id删除", notes = "采购订货-通过id删除")
    @RequiresPermissions("wmhb:purchase_order_detail:delete")
    @DeleteMapping(value = "/delete")
    public Result<String> delete(@RequestParam(name = "id", required = true) String id) {
        purchaseOrderDetailService.removeById(id);
        return Result.OK("删除成功!");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "采购订货-批量删除")
    @ApiOperation(value = "采购订货-批量删除", notes = "采购订货-批量删除")
    @RequiresPermissions("wmhb:purchase_order_detail:deleteBatch")
    @DeleteMapping(value = "/deleteBatch")
    public Result<String> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        this.purchaseOrderDetailService.removeByIds(Arrays.asList(ids.split(",")));
        return Result.OK("批量删除成功!");
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    //@AutoLog(value = "采购订货-通过id查询")
    @ApiOperation(value = "采购订货-通过id查询", notes = "采购订货-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<WmPurchaseOrderDetail> queryById(@RequestParam(name = "id", required = true) String id) {
        WmPurchaseOrderDetail purchaseOrderDetail = purchaseOrderDetailService.getById(id);
        if (purchaseOrderDetail == null) {
            return Result.error("未找到对应数据");
        }
        return Result.OK(purchaseOrderDetail);
    }

    /**
     * 导出excel
     *
     * @param request
     * @param purchaseOrderDetail
     */
    @RequiresPermissions("wmhb:purchase_order_detail:exportXls")
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, WmPurchaseOrderDetail purchaseOrderDetail) {
        return super.exportXls(request, purchaseOrderDetail, WmPurchaseOrderDetail.class, "采购订货");
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    @RequiresPermissions("wmhb:purchase_order_detail:importExcel")
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    @Transactional
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            // 获取上传文件对象
            MultipartFile file = entity.getValue();
            Integer sheetNum = 1;
            Workbook workbook = null;
            try {
                workbook = WorkbookFactory.create(file.getInputStream());
                sheetNum = workbook.getNumberOfSheets();//读取sheet的数量
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }

            ImportParams params = new ImportParams();
            params.setStartSheetIndex(0); //从第几个sheet页开始读取
            params.setSheetNum(sheetNum); //读取几个sheet页
            params.setTitleRows(1);       //标题不能为空，否则跳过该行
            params.setHeadRows(1);
            params.setNeedSave(false);
            try(InputStream inputStream = file.getInputStream()) {
                List<WmPurchaseOrderDetail> list = ExcelImportUtil.importExcel(inputStream, WmPurchaseOrderDetail.class, params);
                WmPurchaseOrderDetailResult wmPurchaseOrderDetailResult = uploadOrderProcess(list);
                return Result.ok(wmPurchaseOrderDetailResult);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                throw new RuntimeException(e.getMessage());
            } finally {
                try {
                    workbook.close();
                    file.getInputStream().close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return Result.error("文件导入失败！");
    }

    private WmPurchaseOrderDetailResult uploadOrderProcess(List<WmPurchaseOrderDetail> list) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        List<WmPurchaseOrderDetail> newList = new ArrayList<>();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        String batchNo = format.format(new Date());
        Integer successNum = 0;
        Integer failNum = 0;
        try {
            for (WmPurchaseOrderDetail bomNode : list) {
                //如果没有这个字段，跳过该行
                if(StringUtils.isEmpty(bomNode.getJdName())){
                    continue;
                }

                //识别订货日期
                if(!StringUtils.isEmpty(bomNode.getOrderDate())) {
                    if(isNumeric(bomNode.getOrderDate())) {
                        Integer numOfOrderDate = Integer.parseInt(bomNode.getOrderDate());
                        bomNode.setOrderDate(convertDaysToDate(numOfOrderDate));
                        //识别供货周期（如果填日期而不是具体天数），要自行计算供货天数
                        if(!StringUtils.isEmpty(bomNode.getSupplyPeriod()) && isNumeric(bomNode.getSupplyPeriod())) {
                            Integer numOfSupplyPeriod = Integer.parseInt(bomNode.getSupplyPeriod());
                            if(numOfSupplyPeriod > 4000 && numOfOrderDate > 4000) {
                                Integer diff = numOfSupplyPeriod - numOfOrderDate;
                                bomNode.setSupplyPeriod(String.valueOf(diff));
                            }
                        }
                    }
                    else{
                        bomNode.setResult("订货日期识别失败");
                        bomNode.setStatus("fail");
                        newList.add(bomNode);
                        failNum++;
                        continue;
                    }
                }

                //识别预计到货时间
                if(!StringUtils.isEmpty(bomNode.getPlanArriveDate())) {
                    if(isNumeric(bomNode.getPlanArriveDate())) {
                        bomNode.setPlanArriveDate(convertDaysToDate(Integer.parseInt(bomNode.getPlanArriveDate())));
                    }
                    else{
                        //bomNode.setResult("预计到货时间识别失败");
                        //bomNode.setStatus("fail");
                        //newList.add(bomNode);
                        //failNum++;
                        //continue;
                        bomNode.setPlanArriveDate(null);
                    }
                }

                //识别到货时间
                if(!StringUtils.isEmpty(bomNode.getFactArriveTime())) {
                    if(isNumeric(bomNode.getFactArriveTime())) {
                        bomNode.setFactArriveTime(convertDaysToDate(Integer.parseInt(bomNode.getFactArriveTime())));
                    }
                    else{
                        bomNode.setResult("到货时间识别失败");
                        bomNode.setStatus("fail");
                        newList.add(bomNode);
                        failNum++;
                        continue;
                    }
                }

                //识别要求到货时间
                if(!StringUtils.isEmpty(bomNode.getRequireArriveTime())) {
                    if(isNumeric(bomNode.getRequireArriveTime())) {
                        bomNode.setRequireArriveTime(convertDaysToDate(Integer.parseInt(bomNode.getRequireArriveTime())));
                    }
                    else{
                        //bomNode.setResult("要求到货时间识别失败");
                        //bomNode.setStatus("fail");
                        //newList.add(bomNode);
                        //failNum++;
                        //continue;
                        bomNode.setRequireArriveTime(null);
                    }
                }

                //识别采购申请时间
                if(!StringUtils.isEmpty(bomNode.getPurchaseApplyTime())) {
                    if(isNumeric(bomNode.getPurchaseApplyTime())) {
                        bomNode.setPurchaseApplyTime(convertDaysToDate(Integer.parseInt(bomNode.getPurchaseApplyTime())));
                    }
                    else{
                        //bomNode.setResult("采购申请时间识别失败");
                        //bomNode.setStatus("fail");
                        //newList.add(bomNode);
                        //failNum++;
                        //continue;
                        bomNode.setPurchaseApplyTime(null);
                    }
                }

                //序号判断，序号为唯一判断值  金蝶合同号或金蝶订单号 和金蝶名称必须不为空
                if (StringUtils.isEmpty(bomNode.getSeriesNo()) && StringUtils.isEmpty(bomNode.getSeriesNo2()) && StringUtils.isEmpty(bomNode.getSeriesNo3())) {
                    //bomNode.setResult("序号缺失");
                    //bomNode.setStatus("fail");
                    //newList.add(bomNode);
                    //failNum++;
                    //continue;
                }

                //如果有物资申请编号而无序号，将物资申请编号复制给序号
                if (StringUtils.isEmpty(bomNode.getSeriesNo()) && !StringUtils.isEmpty(bomNode.getSeriesNo2())){
                    bomNode.setSeriesNo(bomNode.getSeriesNo2());
                }
                //如果有报料序号而无序号，将报料序号复制给序号
                if (StringUtils.isEmpty(bomNode.getSeriesNo()) && !StringUtils.isEmpty(bomNode.getSeriesNo3())){
                    bomNode.setSeriesNo(bomNode.getSeriesNo3());
                }

                //如果有订货编号而无订货单号，将订货编号复制给订货单号
                if (StringUtils.isEmpty(bomNode.getPurchaseOrderNo()) && !StringUtils.isEmpty(bomNode.getPurchaseOrderNo2())){
                    bomNode.setPurchaseOrderNo(bomNode.getPurchaseOrderNo2());
                }

                //如果有需求数量而无数量
                if (StringUtils.isEmpty(bomNode.getQuantity()) && !StringUtils.isEmpty(bomNode.getQuantity2())){
                    bomNode.setQuantity(bomNode.getQuantity2());
                }

                //没有到货数量字段时，到货数量等于数量
                if(StringUtils.isEmpty(bomNode.getArriveQuantity())){
                    bomNode.setArriveQuantity(bomNode.getQuantity());
                }

                //判断是否重复导入
                if(!StringUtils.isEmpty(bomNode.getSeriesNo())) {
                    //如果有序号，则根据序号判断唯一性
                    List<WmPurchaseOrderDetail> wmPurchaseOrderDetailList = purchaseOrderDetailService.searchBySeriesNo(bomNode.getSeriesNo());
                    if (!wmPurchaseOrderDetailList.isEmpty()) {
                        bomNode.setResult("更新成功");
                        bomNode.setStatus("success");
                        newList.add(bomNode);
                        successNum++;
                        //更新数据
                        purchaseOrderDetailService.updateBySeriesNoAndRemark(bomNode);
                        continue;
                    }
                }
                else if(!StringUtils.isEmpty(bomNode.getContractNo())){
                    //如果没有序号，有合同号，则根据合同号和金蝶名称判断唯一性
                    List<WmPurchaseOrderDetail> wmPurchaseOrderDetailList = purchaseOrderDetailService.searchByContractAndJdName(bomNode.getContractNo(), bomNode.getJdName());
                    if (!wmPurchaseOrderDetailList.isEmpty()) {
                        bomNode.setResult("更新成功");
                        bomNode.setStatus("success");
                        newList.add(bomNode);
                        successNum++;
                        //更新数据
                        purchaseOrderDetailService.updateByContractAndJdName(bomNode);
                        continue;
                    }
                }
                else if(!StringUtils.isEmpty(bomNode.getJdOrderNo())){
                    //如果没有序号，有金蝶订单号，则根据金蝶订单号和金蝶名称判断唯一性
                    List<WmPurchaseOrderDetail> wmPurchaseOrderDetailList = purchaseOrderDetailService.searchByJdOrderAndJdName(bomNode.getContractNo(), bomNode.getJdName());
                    if (!wmPurchaseOrderDetailList.isEmpty()) {
                        bomNode.setResult("更新成功");
                        bomNode.setStatus("success");
                        newList.add(bomNode);
                        successNum++;
                        //更新数据
                        purchaseOrderDetailService.updateByJdOrderAndJdName(bomNode);
                        continue;
                    }
                }

                //插入数据
                bomNode.setResult("导入成功");
                bomNode.setStatus("success");
                bomNode.setBatchNo(batchNo);
                bomNode.setUserId(sysUser.getId());
                bomNode.setUsername(sysUser.getRealname());
                successNum++;
                purchaseOrderDetailService.save(bomNode);
                newList.add(bomNode);
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        WmPurchaseOrderDetailResult wmPurchaseOrderDetailResult = new WmPurchaseOrderDetailResult();
        wmPurchaseOrderDetailResult.setPurchaseOrderDetailList(newList);
        wmPurchaseOrderDetailResult.setBatchNo(batchNo);
        wmPurchaseOrderDetailResult.setResult("导入成功"+ successNum + "条，导入失败" + failNum + "条");
        return wmPurchaseOrderDetailResult;
    }

    private String convertDaysToDate(int totalDays) {
        Date javaDate = DateUtil.getJavaDate((double) totalDays);
        return new SimpleDateFormat("yyyy-MM-dd").format(javaDate);
    }

    private Boolean isNumeric(String str) {
        return str.matches("\\d+"); // 正则表达式 \d 是数字字符，+ 表示一次或多次。
    }

}
